/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.toolbox.structure;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.toolbox.structure
 * @author:LiBo/Alex
 * @create-date:2020-04-07 20:59
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 */
public class LinkHandler {

    private LinkList linkList;
    /**
     * 节点对象
     * @param <T>
     */
    @Getter
    @Setter
    public class Node<T>{

        /**
         * 数据对象
         */
        private T value;

        /**
         * 左边节点
         */
        private Node<T> left;

        /**
         * 右边节点
         */
        private Node<T> right;



        Node(T data) {
            this.value = data;
            this.left = null;
            this.right = null;
        }

    }

    /**
     * 链表对象
     */
    @Getter
    public  class LinkList<T>{
        /**
         * 头节点
         */
        private Node<T> head;

        /**
         * 尾节点
         */
        private Node<T> tail;

        /**
         * 当前节点
         */
        private Node<T> current;

        /**
         * 如果头节点为空，则赋值为当前节点
         * 如果头节点不为空，则要双向设置，当前节点向后移动一位
         * @param data
         * @return
         */
        T add(T data){
            // 如果头节点为空!
            if(Objects.isNull(head) ){
                head = new Node<>(data);
                tail = head;
                current = head;
            }else{
                // 创建临时节点
                Node<T> tmp = new Node<>(data);
                //赋值尾节点
                tail = tmp;
                // 把新建的的节点放到当前的节点的后面
                current.setRight(tmp);
                // 添加的节点链表指针为前面节点为(双向绑定)
                tmp.setLeft(current);
                // 把当前指针指向当前数据节点（tmp）
                current = current.getRight();
            }
            return data;
        }

        /**
         * 正序
         * @return
         */
        List<Node<T>> asc(){
            return asc(null);
        }

        /**
         * 正序
         * @return
         */
        List<Node<T>> asc(Node<T> dataNode){
            List<Node<T>> dataList = new LinkedList<>();
            if(Objects.isNull(dataNode)){
               dataNode = this.head;
            }
            do{
                dataList.add(dataNode);
                dataNode = dataNode.right;
            }while((dataNode != null));
            return dataList;
        }

        /**
         * 正序
         * @return
         */
        List<Node<T>> desc(){
            return desc(null);
        }

        /**
         * 正序
         * @return
         */
        List<Node<T>> desc(Node<T> dataNode){
            List<Node<T>> dataList = new LinkedList<>();
            if(Objects.isNull(dataNode)){
                dataNode = this.tail;
            }
            do{
                dataList.add(dataNode);
                dataNode = dataNode.left;
            }while((dataNode != null));
            return dataList;
        }

        /**
         * 链表倒置
         */
        void reverse() {
            if (head == null || head.getRight() == null) {
                return;
            }
            current = head;
            while(true) {
                //交换左右节点
                Node<T> tmp = head.getLeft();
                head.setLeft(head.getRight());
                head.setRight(tmp);
                //如果左节点为空，则终止，否则循环执行
                if (head.getLeft() == null) {
                    tail = current;
                    return;
                } else {
                    head = head.getLeft();
                }
            }
        }
    }

    public LinkHandler() {
        this.linkList = create();
    }

    /**
     * 创建列表对象
     * @return
     */
    LinkList create(){
         this.linkList = new LinkList<>();
         return linkList;
    }

    /**
     * 构建获取当前集合对象实例
     * @param <T>
     * @return
     */
    public <T> LinkList<T> get(){
        return linkList;
    }


    /**
     * 添加元素
     * @param <T>
     * @return
     */
    public <T> Object add(T data){
        Objects.requireNonNull(this.linkList,"必须先初始化创建集合对象 create方法");
        return linkList.add(data);
    }


    public <T> List<Node<T>> asc(){
        Objects.requireNonNull(this.linkList,"必须先初始化创建集合对象 create方法");
        return linkList.asc();
    }


    public <T> List<Node<T>> desc(){
        Objects.requireNonNull(this.linkList,"必须先初始化创建集合对象 create方法");
        return linkList.desc();
    }


    public LinkHandler reverse(){
        Objects.requireNonNull(this.linkList,"必须先初始化创建集合对象 create方法");
        this.linkList.reverse();
        return this;
    }

}
